﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.IO;
using ParsecParser.Data;
using ParsecParser.Helpers;

namespace ParsecParser
{
    [Serializable]
    public class CombatLogEvent
    {
        public int EventId { get; set; }
        public string CharacterName { get; set; }
        public string RawString { get; set; }
        public DateTime TimeStamp { get; set; }

        public CombatLogParticipant Source { get; set; }
        public CombatLogParticipant Target { get; set; }
        public CombatLogEntity Ability { get; set; }
        public CombatLogEntity EffectType { get; set; }
        public CombatLogEntity EffectName { get; set; }
        public CombatLogEntity Mitigation { get; set; }
        public CombatLogEntity DamageType { get; set; }
        public CombatLogEntity DamageModifier { get; set; }
        public CombatLogEntity AbsorbType { get; set; }

        public bool IsCrit { get; set; }
        public int HitIndex { get; set; }
        public int Value { get; set; }
        public int AbsorbedValue { get; set; }
        public long Threat { get; set; }
        public int EffectiveHeal { get; set; }
        public int FightIndex { get; set; }

        public CombatLogEvent()
        {
            Source = new CombatLogParticipant();
            Target = new CombatLogParticipant();
            Ability = null;
            EffectType = null;
            EffectName = null;
            Mitigation = null;
            DamageType = null;
            AbsorbType = null;
            DamageModifier = null;
        }
        public override string ToString()
        {
            return ToString(null, false);
        }
        public string ToString(string characterName, bool isHtml)
        {
            string integerFormat = "N0";
            bool isSource = false;
            bool isTarget = false;
            CombatLogEntity EmptyEntity = new CombatLogEntity(CombatLogEntity.EmptyEntityName, 0);
            string timeStamp = TimeStamp.ToString("HH:mm:ss.fff");
            if (!string.IsNullOrEmpty(characterName) && Source.IsPlayer && (characterName == Source.DisplayName) && !Source.IsPlayerCompanion)
                isSource = true;
            if (!string.IsNullOrEmpty(characterName) && Target.IsPlayer && (characterName == Target.DisplayName) && !Target.IsPlayerCompanion)
                isTarget = true;
            switch ((EffectType ?? EmptyEntity).EntityId)
            {
                case CombatLogConstants.EffectTypes.ApplyEffect:
                    {
                        switch ((EffectName ?? EmptyEntity).EntityId)
                        {
                            case CombatLogConstants.EffectNames.Damage:
                                {
                                    string source, target, format,ability;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">" + (isSource ? "yourself" : "you") + "</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        ability = string.Format(isTarget ? "<span class=\"AttackInAbilityName Popable\" data-tooltiptext=\"{0}\">" + (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") + "</span>" : "<span class=\"AttackOutAbilityName Popable\" data-tooltiptext=\"{0}\">" + (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") + "</span>", (Ability ?? EmptyEntity).EntityId);
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3} with {4} for <span class=\"DamageAmount\">{5}</span><span class=\"Mitigation\">{6}{7}</span> damage<span class=\"Threat\">{8}</span>";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? (isSource ? "yourself" : "you") : Target.DisplayNameWithOwner.Escape(isHtml); 
                                        ability = (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability");
                                        format = "{0} {1} {2} {3} with {4} for {5}{6}{7} damage{8}";
                                    }
                                    bool isGlance = Mitigation != null && Value > 0;
                                    string verb = isSource ? "hit" : "hits";
                                    string damage = (Value - AbsorbedValue).ToString(integerFormat) + (IsCrit ? "*" : "") + (DamageType != null ? " " + DamageType.DisplayName.Escape(isHtml) : "");
                                    string absorb = (AbsorbType != null && AbsorbedValue > 0) ? string.Format(" (absorbed {0})", AbsorbedValue.ToString(integerFormat)) : "";
                                    string mitigated = Mitigation != null ? " (" + Mitigation.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Mitigation") + ")" : "";
                                    string threat = !isTarget && Threat != 0 ? " (" + Threat.ToString(integerFormat) + " threat)" : "";
                                    return string.Format(format, timeStamp, source, verb, target, ability, damage, mitigated, absorb, threat);
                                }
                            case CombatLogConstants.EffectNames.Heal:
                                {
                                    string source, target, format, healDetail, ability;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">" + (isSource ? "yourself" : "you") + "</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        int overhealAmount = Value - EffectiveHeal;
                                        healDetail = isSource && overhealAmount > 2 ? " <span class=\"EffectiveHealAmount\">(" + EffectiveHeal.ToString(integerFormat) + " effective)</span>" : "";
                                        ability = string.Format("<span class=\"HealAbilityName Popable\" data-tooltiptext=\"{0}\">", (Ability ?? EmptyEntity).EntityId.ZeroToNull()) + (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3} with {4} for <span class=\"HealAmount\">{5}</span>{6}<span class=\"Threat\">{7}</span>";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? (isSource ? "yourself" : "you") : Target.DisplayNameWithOwner.Escape(isHtml);
                                        int overhealAmount = Value - EffectiveHeal;
                                        healDetail = overhealAmount > 2 ? " (" + EffectiveHeal.ToString(integerFormat) + " effective)" : "";
                                        ability = (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability");
                                        format = "{0} {1} {2} {3} with {4} for {5}{6}{7}";
                                    }
                                    string verb = isSource ? "heal" : "heals";
                                    string threat = Threat != 0 ? " (" + Threat.ToString(integerFormat) + " threat)" : "";
                                    return string.Format(format, timeStamp, source, verb, target, ability, Value.ToString(integerFormat), healDetail, threat);
                                }

                            default:
                                {
                                    string source, target, format, effectclass;
                                    if (isHtml)
                                    {
                                        source = isSource || Source.CompareTo(Target) == 0 ? "" : " from " + string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        effectclass = isTarget && !Source.IsPlayer && !Source.IsPlayerCompanion ? "NpcEffectName" : "EffectName";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"{6} Popable\" data-tooltiptext=\"{5}\">{3}</span>{4}<span class=\"Threat\">{7}</span>";
                                    }
                                    else
                                    {
                                        source = isSource || Source.CompareTo(Target) == 0 ? "" : " from " + Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? "You" : Target.DisplayNameWithOwner.Escape(isHtml);
                                        effectclass = null;
                                        format = "{0} {1} {2} {3}{4}{7}";
                                    }
                                    string verb = isTarget ? "gain" : "gains";
                                    string effect = (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Effect");
                                    string threat = Threat != 0 ? " (" + Threat.ToString(integerFormat) + " threat)" : "";
                                    return string.Format(format, timeStamp, target, verb, effect, source, (EffectName ?? EmptyEntity).EntityId.ZeroToNull(), effectclass, threat);
                                }
                        }
                    }
                case CombatLogConstants.EffectTypes.RemoveEffect:
                    {
                        string source, target, format, effect;
                        if (isHtml)
                        {
                            source = isSource ? (isTarget ? "" : "<span class=\"YouParty\">your</span> ") : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + (Source.DisplayNameWithOwner + "'s").Escape(isHtml) + "</span> ";
                            target = isTarget ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                            string effectclass = isTarget && !Source.IsPlayer && !Source.IsPlayerCompanion ? "NpcEffectName" : "EffectName";
                            effect = string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">{2}</span> effect", effectclass, (EffectName ?? EmptyEntity).EntityId.ZeroToNull(), (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml));
                            format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3}{4}";
                        }
                        else
                        {
                            source = isSource ? (isTarget ? "" : "your ") : (Source.DisplayNameWithOwner + "'s ").Escape(isHtml);
                            target = isTarget ? "You" : Target.DisplayNameWithOwner.Escape(isHtml);
                            effect = (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml) + " effect";
                            format = "{0} {1} {2} {3}{4}";
                        }
                        string verb = isTarget ? "lose" : "loses";
                        return string.Format(format, timeStamp, target, verb, source, effect);
                    }
                case CombatLogConstants.EffectTypes.Event:
                    {
                        switch ((EffectName ?? EmptyEntity).EntityId)
                        {
                            case CombatLogConstants.EffectNames.AbilityActivate:
                            case CombatLogConstants.EffectNames.AbilityCancel:
                            case CombatLogConstants.EffectNames.AbilityDeactivate:
                            case CombatLogConstants.EffectNames.AbilityInterrupt:
                                {
                                    string source, target, format, verb;
                                    if (isHtml)
                                    {
                                        source = isSource && !Source.IsPlayerCompanion ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget && !Target.IsPlayerCompanion ? "" : " on " + string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        if (Target.DisplayName == CombatLogParticipant.EmptyParticipantName && ((EffectName ?? EmptyEntity).EntityId) == CombatLogConstants.EffectNames.AbilityInterrupt)
                                            target = null;
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"AbilityName Popable\" data-tooltiptext=\"{5}\">{3}</span>{4}";
                                    }
                                    else
                                    {
                                        source = isSource && !Source.IsPlayerCompanion ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget && !Target.IsPlayerCompanion ? "" : " on " + Target.DisplayNameWithOwner.Escape(isHtml);
                                        format = "{0} {1} {2} {3}{4}";
                                    }
                                    string ability = (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability");
                                    if ((EffectName ?? EmptyEntity).EntityId == CombatLogConstants.EffectNames.AbilityActivate)
                                        verb = isSource ? "activate" : "activates";
                                    else if ((EffectName ?? EmptyEntity).EntityId == CombatLogConstants.EffectNames.AbilityCancel)
                                        verb = isSource ? "cancel" : "cancels";
                                    else if ((EffectName ?? EmptyEntity).EntityId == CombatLogConstants.EffectNames.AbilityDeactivate)
                                        verb = isSource ? "deactivate" : "deactivates";
                                    else if ((EffectName ?? EmptyEntity).EntityId == CombatLogConstants.EffectNames.AbilityInterrupt)
                                        verb = isSource ? "interrupt" : "interrupts";
                                    else
                                        verb = isSource ? "do something to" : "does something to";
                                    return string.Format(format, timeStamp, source, verb, ability, target, (Ability ?? EmptyEntity).EntityId.ZeroToNull());
                                }
                            case CombatLogConstants.EffectNames.EnterCombat:
                            case CombatLogConstants.EffectNames.ExitCombat:
                                {
                                    string source, format, verb;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} <span class=\"CombatEvent\">{2}</span><span class=\"Threat\">{3}</span>";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        format = "{0} {1} {2}{3}";
                                    }
                                    if ((EffectName ?? EmptyEntity).EntityId == CombatLogConstants.EffectNames.EnterCombat)
                                        verb = isSource ? "enter combat" : "enters combat";
                                    else
                                        verb = isSource ? "exit combat" : "exits combat";
                                    string threat = Threat != 0 ? " (" + Threat.ToString(integerFormat) + " threat)" : "";
                                    return string.Format(format, timeStamp, source, verb, threat);
                                }
                            case CombatLogConstants.EffectNames.ModifyThreat:
                                {
                                    string source, target, format, ability;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">your</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        ability = string.Format(isTarget ? "<span class=\"AttackOutAbilityName Popable\" data-tooltiptext=\"{0}\">" + (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") + "</span>" : "<span class=\"AttackInAbilityName Popable\" data-tooltiptext=\"{0}\">" + (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") + "</span>", (Ability ?? EmptyEntity).EntityId);
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3} threat on {4} to change by <span class=\"Threat\">{5}</span>";
                                    }
                                    else
                                    {
                                        source = isSource ? "your" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? "You" : Target.DisplayNameWithOwner.Escape(isHtml);
                                        ability = Ability.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability");
                                        format = "{0} {1} {2} {3} threat on {4} to change by {5}";
                                    }
                                    string verb = isSource ? "causes" : "cause";
                                    string threat = Threat.ToString(integerFormat);
                                    return string.Format(format, timeStamp, ability, verb, source, target, threat);
                                }
                            case CombatLogConstants.EffectNames.FailedEffect:
                                {
                                    string source, format, ability;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">Your</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml).MakePossessive() + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} failed";
                                        ability = string.Format("<span class=\"AbilityName Popable\" data-tooltiptext=\"{0}\">{1}</span>", (Ability ?? EmptyEntity).EntityId, (Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability"));
                                    }
                                    else
                                    {
                                        source = isSource ? "Your" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        ability =(Ability ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability");
                                        format = "{0} {1} {2} failed";
                                    }
                                    return string.Format(format, timeStamp, source, ability);
                                }
                            case CombatLogConstants.EffectNames.FallingDamage:
                                {
                                    string source, format;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3}";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        format = "{0} {1} {2} {3}";
                                    }
                                    string verb = isSource ? "take falling damage" : "takes falling damage";
                                    string damage = Value.ToString(integerFormat);
                                    return string.Format(format, timeStamp, source, verb, damage);
                                }
                            case CombatLogConstants.EffectNames.Taunt:
                                {
                                    string source, target, format;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">you</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"AbilityName\">{3}</span><span class=\"Threat\">{4}</span>";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? "you" : Target.DisplayNameWithOwner.Escape(isHtml);
                                        format = "{0} {1} {2} {3}{4}";
                                    }
                                    string verb = isSource ? "taunt" : "taunts";
                                    string threat = !isTarget && Threat != 0 ? " (" + Threat.ToString(integerFormat) + " threat)" : "";
                                    return string.Format(format, timeStamp, source, verb, target, threat);
                                }
                            case CombatLogConstants.EffectNames.Death:
                                {
                                    string source, target, format;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">you</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} {3}";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? "you" : Target.DisplayNameWithOwner.Escape(isHtml);
                                        format = "{0} {1} {2} {3}";
                                    }
                                    string verb = isSource ? "kill" : "kills";
                                    return string.Format(format, timeStamp, source, verb, target);
                                }
                            default:
                                {
                                    string source, target, format, ability, eventValue;
                                    if (isHtml)
                                    {
                                        source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        target = isTarget ? "<span class=\"YouParty\">you</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                                        ability = Ability != null ? string.Format(" with <span class=\"AbilityName Popable\" data-tooltiptext=\"{1}\">{0}</span>", Ability.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability"), Ability.EntityId.ZeroToNull()) : "";
                                        eventValue = Value > 0 ? " with value <span class=\"AbilityValue\">" + Value.ToString(integerFormat) + "</span>" : "";
                                        format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"EventName\">{3}</span> on {4}{5}{6}";
                                    }
                                    else
                                    {
                                        source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                                        target = isTarget ? "you" : Target.DisplayNameWithOwner.Escape(isHtml);
                                        ability = Ability != null ? " with " + Ability.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") : "";
                                        eventValue = Value > 0 ? " with value " + Value.ToString(integerFormat) : "";
                                        format = "{0} {1} {2} {3} on {4}{5}{6}";
                                    }
                                    string verb = isSource ? "cause event" : "causes event";
                                    string eventName = (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Effect");
                                    return string.Format(format, timeStamp, source, verb, eventName, target, ability, eventValue);
                                }
                        }
                    }
                case CombatLogConstants.EffectTypes.Spend:
                case CombatLogConstants.EffectTypes.Restore:
                    {
                        string source, verb, format;
                        if (isHtml)
                        {
                            source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                            format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"Resource\">{3} {4}</span>";
                        }
                        else
                        {
                            source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                            format = "{0} {1} {2} {3} {4}";
                        }
                        if (EffectType.EntityId == CombatLogConstants.EffectTypes.Spend)
                            verb = isSource ? "spend" : "spends";
                        else
                            verb = isSource ? "restore" : "restores";
                        string spendType = (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Resource");
                        return string.Format(format, timeStamp, source, verb, Value.ToString(integerFormat), spendType);
                    }
                default:
                    {
                        string source, target, ability, format;
                        if (isHtml)
                        {
                            source = isSource ? "<span class=\"YouParty\">You</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Source.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Source.EntityId.ZeroToNull()) + Source.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                            target = isTarget ? "<span class=\"YouParty\">you</span>" : string.Format("<span class=\"{0} Popable\" data-tooltiptext=\"{1}\">", (Target.IsPlayer ? "OtherPartyPlayer" : "OtherParty"), Target.EntityId.ZeroToNull()) + Target.DisplayNameWithOwner.Escape(isHtml) + "</span>";
                            ability = Ability != null ? string.Format(" with <span class=\"AbilityName Popable\" data-tooltiptext=\"{1}\">{0}</span>", Ability.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability"), Ability.EntityId.ZeroToNull()) : "";
                            format = "<span class=\"TimeStamp\">{0}</span> {1} {2} <span class=\"EffectName Popable\" data-tooltiptext=\"{7}\">{3}</span> <span class=\"EffectName Popable\" data-tooltiptext=\"{8}>{4}</span> on {5}{6}";
                        }
                        else
                        {
                            source = isSource ? "You" : Source.DisplayNameWithOwner.Escape(isHtml);
                            target = isTarget ? "you" : Target.DisplayNameWithOwner.Escape(isHtml);
                            ability = Ability != null ? " with " + Ability.DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Ability") : "";
                            format = "{0} {1} {2} {3} {4} on {5}{6}";
                        }
                        string verb = isSource ? "cause " : "causes ";
                        string eventType = (EffectType ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Effect Type");
                        string eventTypeId = (EffectType ?? EmptyEntity).EntityId.ZeroToNull();
                        string eventName = (EffectName ?? EmptyEntity).DisplayName.Escape(isHtml).Replace(CombatLogEntity.EmptyEntityName, "Unknown Event");
                        string eventNameId = (EffectName ?? EmptyEntity).EntityId.ZeroToNull();
                        return string.Format(format, timeStamp, source, verb, eventType, eventName, target, ability, eventTypeId, eventNameId);
                    }
            }
        }
    }
    public static class StringHelper
    {
        public static string Escape(this string s, bool isHtml)
        {
            if (!isHtml)
                return s;
            return System.Net.WebUtility.HtmlEncode(s); //System.Security.SecurityElement.Escape(s);
        }
        public static string ZeroToNull(this long l)
        {
            if (l == 0)
                return null;
            else
                return l.ToString();
        }
    }
}
